Unity3D Building Damage Tutorial- Part V - Thick Mesh
Okay. Now, we have a one-sided mesh without thickness. When it is static, it may seem ok, but as soon as destruction starts, we "see" invisible interior and super-thick walls. Of course it seems impossible. So, to overcome this, i decided to give meshes thickness. My Aim here is to: *Produce an "interior" mesh facing inwards. Number of its verticles, Aliases and Triangles will be the same as outer mesh. You may visualise it that way: First, we have a mesh. Than, we scale it down a little and make its triangles face to the interior, as this triangles are visible only on one way. Another way, to overcome this problem would be to fizzle with shaders, but i'm not expert into this. Anyway, to get to the aim, we will have to get through several steps. #Make some starting method, like MakeTheMeshThick() #Make copy of ALL aliases. (I will name this copies "twins") #Slightly change position of this twins. #Add offseting to twins data. (I will talk about it in a moment) #Invert Triangles of twins (to face opposite way) #Update VerticleToAliasArray #Update mesh.verticle (new method!) #Update mesh.triangles(old method) Offseting So, when i was thinking about this, i realised of something. Lets say, that we have a simple cube, like than in that picture. It has 8 Aliases. Lets say of numbers 1-8. 'In fact, they would have numbers 0-7, but i have made a mistake. ' In addition 12 triangles and 36 verticles. Than, we add inside "twin cube". An offset of Aliases would be its number in pervious cube, in this case 8. An twin of Alias number 2 would be 2 + 8 = 10. In that way we can easily calculate numbers of every twin. A twin of triangle number 10 would be 10+12 = 22. etc. MakeMeshThick() Method Well, the starting method. It will be called lets say in StartFire, so when player clicks on the building. public void MakeMeshThick(){ List NewAliases = MakeAliasesTwin(Aliases); List NewTriangles = InvertTrianglesGivingListOfTriangles(Triangles); NewTriangles = AddOffsetToTriangleList(NewTriangles, mesh.vertices.Length); AddTwinsToVerticleToAliasArray(); for(int i=0; i MakeAliasesTwin(List XAliases){ float Wall_Thickness = 0.005f; Vector3 TargetPosition; Vector3 NewPosition ; int offset = Aliases.Count; List NewAliases = new List(); for(int i=0; ifloat Wall_Thickness = 0.005f; Hard coded distance between an Alias and its twin. Later, I'll change it, and will not be hard coded of course. *Vector3 TargetPosition; Vector3 NewPosition ; Two Vector3. Will be used later. *int offset = Aliases.Count; Here I just count the offset. *List NewAliases = new List(); Making a new List of Verticles. Here we will add the twins (changed Aliases) *TargetPosition = XAliasesi.positionRelative-(XAliasesi.normal); This is intresting. But before I am going to explain this, simple question. How we are going to know, which way we should move the Alias, for it to be "in" the mesh. First, i thought about scaling, but that was working well only with simple meshes with its "center" position in absolute inside. Than, I found out about vertex normals. More specific data can be found on wiki. What is intresting for us, is that in mesh.normals there are some specific vector3 for every variable. This are vectors pointing outside from the mesh, like in the picture. Using then, we can easily count the twin position. TargetPosition = XAliasesi.positionRelative-(XAliasesi.normal); NewPosition = Vector3.MoveTowards(XAliasesi.positionRelative, TargetPosition, Wall_Thickness); Two lines, two intresting things. First, i count TargetPosition, by decreasing the relativePosition of Alias by the normal value. (Decreasing!. We want a point inside the mesh, not outside.) Simple modification was made in Verticle.cs public Vector3 normal; //...................... public Verticle(MeshManager Owner ,int Xnumber, List XAliases, Vector3 XpositionRelative){ //................................ normal = OwnerManager.mesh.normals[Aliases0]; Well, for some reason, every verticle in the same position has the same normal, so I simply check the normal of first one. *Getting back to code, First we count the "targetPosition" The normal is only a direction so we cannot use it as a real point. This point first has to be calculated, and than moved from/to it. *NewPosition = Vector3.MoveTowards(XAliasesi.positionRelative, TargetPosition, Wall_Thickness); And here we calculate the point. We are moving from the Alias relative position to the TargetPosition by the "Wall Thickness" NewAliases.Add(new Verticle(this,XAliasesi.number+offset,XAliasesi.Aliases,NewPosition) );//copy an alias Here, i add a new Alias (a twin) to our List. Lets look deeper. *new Verticle(this,XAliasesi.number+offset,XAliasesi.Aliases,NewPosition) Using normal constructor. In more detail it is explained here. Anway, i pass the MeshManager, new number (the number of Alias + offset), aliases of this Alias (modified in a minute) and the new position. NewAliasesi.AddOffsetToAliases(mesh.vertices.Length); We have to modify the aliases (the numbers of vertilces which form an Alias). The function code //In Verticles.cs public void AddOffsetToAliases(int offset){ for(int i=0; ireturn NewAliases; Than i simply return that list. Great, we have points 1-4 from my list, now, getting back to MakeMeshThick List NewTriangles = InvertTrianglesGivingListOfTriangles(Triangles); We have a list of Vector3s named NewTriangles and a method InvertTrianglesGivingListOfTriangles. InverttrianglesGivingListOfTriangles method Before I'll go to code, how had I inverted them. Well, apparently one way to invert the traingles is to invert the order of verticles in mesh.triangles. From mesh.triangles = new int[] {0,1,3 , 1,2,5 ....} to {3,1,0 , 5,2,1, ....}. Well, it works and by doint that we preserve the original numbers of triangles (The twin triangle of triangle number 3 would be 3 + offset(the original number of triangles), but it would face other direction.) private List InvertTrianglesGivingListOfTriangles(List XTriangles = null){ if(XTriangles null){XTriangles = Triangles;} List temp = new List(); for(int i=0;i } private List InvertTrianglesGivingListOfTriangles(List XTriangles = null){ if(XTriangles null){XTriangles = Triangles;} Here the list of Triangles is optional parameter. Maybe not allways we will want to use the current Triangles list. Using this optional we can start this method by both InvertTrianglesGivingListOfTriangles() and InvertTrianglesGivingListOfTriangles(OtherListOfTriangles) *List temp = new List(); We declare and initialise new list, and then we have loop for(int i=0;i temp.Add( new Vector3(XTriangles[ i].z,XTriangles[ i].y,XTriangles[ i].x ) ); } *Well, we just invert the order in each Vector3 (but not invert the order of Vector3s) return temp; And then we return this List. AddOffsetToTriangleList method Well, we still have to add the offset to this list. This might have been done in pervious metod, but i made additional function for this. //In MakeMeshThick NewTriangles = AddOffsetToTriangleList(NewTriangles, mesh.vertices.Length); private List AddOffsetToTriangleList(List XTriangles, int offset){ List Temp = new List(); for(int i=0; iint[] NewVTAA = new intVerticleToAliasArray.Length; A new array. VTAA means VerticleToAraryAlias. It has lenght of original VTAA. *int offset = Aliases.Count; Counting offset. for(int i=0; i VerticleToAliasArray.CopyTo(z, 0); NewVTAA.CopyTo(z, VerticleToAliasArray.Length); VerticleToAliasArray = z; *This is maybe a bit overcomplicated merging of two arrays. I am sure that there are ways to do this simpler and shorter, but at least it works. Back To MakeMeshThick method for(int i=0; i Aliasesi.DoHaveTwin = true; } Aliases.AddRange(NewAliases); Triangles.AddRange(NewTriangles); UpdateVerticlesList(); UpdateTrianglesList(); } First, there is that that for loop. Well, it changes a new property of Verticle Class public bool DoHaveTwin = false; to true. It is changed only in original Aliases, as every of them will have a twin. Aliases.AddRange(NewAliases); Triangles.AddRange(NewTriangles); This is simply adding NewAliases at the end of Aliases and the same thing at Triangles. UpdateVerticleList method New method, translating from List of Aliases to mesh.verticle array public void UpdateVerticlesList(){ Vector3[] temp = new Vector3VerticleToAliasArray.Length; for(int i=0; i< VerticleToAliasArray.Length; i++){ int k = VerticleToAliasArrayi; tempi = Aliasesk.positionRelative; } mesh.vertices = temp; } I make new Vector3 array, with lenght of VerticleToAliasArray, as VTAA lenght has been updated (doubled) before.Than we have got a for loop and int k = VerticleToAliasArrayi; //Get the number of Alias having this particular verticle tempi = Aliasesk.positionRelative; // Set position, as Alias position is the same as position of verticle being in Alias Than, simple update of verticles array. mesh.vertices = temp; Ending Updating triangles is the same as before. Now, if we look into a mesh there will be untextured area, as uv has not been yet changed. For files, go to Github . Category:Unity3D Building Damage Tutorial Category:Unity3D Category:C Sharp